/*
Copyleft 2007 by T.S.Yo
*/


package exp.util;
import ec.simple.*;
import ec.*;
import ec.util.Checkpoint;

/* 
 * MyExpBreeder.java
 * 
 * Created: 2007.03.29
 * By: T.S.Yo
 */

/**
 * MyExpEvolutionState is a modification of SimpleEvolutionState.
 * 
 * - no elitism
 * - generates offsprings with random selection, and forms another population
 * - final selection on the union of the original population plus the newly generated population
 *
 * @author T.S.Yo
 * @version 1.0 
 */


public class MyExpEvolutionState extends SimpleEvolutionState
    {

    /** Unchanged methods
     * 
    public void startFresh()
    public void finish(int result) 
     */

    /**
     * @return
     * @throws InternalError
     */
    public int evolve()
        {
        if (generation > 0) 
            output.message("Generation " + generation);

        // EVALUATION
        statistics.preEvaluationStatistics(this);
        evaluator.evaluatePopulation(this);
        statistics.postEvaluationStatistics(this);

        // SHOULD WE QUIT?
        if (evaluator.runComplete(this) && quitOnRunComplete)
            {
            output.message("Found Ideal Individual");
            return R_SUCCESS;
            }

        // SHOULD WE QUIT?
        if (generation == numGenerations-1)
            {
            return R_FAILURE;
            }
            
        // PRE-BREEDING EXCHANGING
        statistics.prePreBreedingExchangeStatistics(this);
        population = exchanger.preBreedingExchangePopulation(this);
        statistics.postPreBreedingExchangeStatistics(this);

        String exchangerWantsToShutdown = exchanger.runComplete(this);
        if (exchangerWantsToShutdown!=null)
            { 
            output.message(exchangerWantsToShutdown);
            /*
             * Don't really know what to return here.  The only place I could
             * find where runComplete ever returns non-null is 
             * IslandExchange.  However, that can return non-null whether or
             * not the ideal individual was found (for example, if there was
             * a communication error with the server).
             * 
             * Since the original version of this code didn't care, and the
             * result was initialized to R_SUCCESS before the while loop, I'm 
             * just going to return R_SUCCESS here. 
             */
            
            return R_SUCCESS;
            }

        // BREEDING
        statistics.preBreedingStatistics(this);
        Population oldPop = this.population;
        Population newPop = breeder.breedPopulation(this);
        
        // EVALUATION
        statistics.preEvaluationStatistics(this);
        evaluator.evaluatePopulation(this);
        statistics.postEvaluationStatistics(this);

        // POST-BREEDING EXCHANGING
        statistics.postBreedingStatistics(this);
            
        // POST-BREEDING EXCHANGING
        statistics.prePostBreedingExchangeStatistics(this);
        population = exchanger.postBreedingExchangePopulation(this);
        statistics.postPostBreedingExchangeStatistics(this);

        // SHOULD WE QUIT?
        if (evaluator.runComplete(this) && quitOnRunComplete)
            {
            output.message("Found Ideal Individual");
            return R_SUCCESS;
            }

        // SHOULD WE QUIT?
        if (generation == numGenerations-1)
            {
            return R_FAILURE;
            }

        // INCREMENT GENERATION AND CHECKPOINT
        generation++;
        if (checkpoint && generation%checkpointModulo == 0) 
            {
            output.message("Checkpointing");
            statistics.preCheckpointStatistics(this);
            Checkpoint.setCheckpoint(this);
            statistics.postCheckpointStatistics(this);
            }

        return R_NOTDONE;
        }

    }
